package com.example.myapplication.realtime

import android.content.Context
import android.util.Log
import com.example.myapplication.User
import com.example.myapplication.UserSession
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.JsonDeserializer
import com.google.gson.JsonDeserializationContext
import com.google.gson.JsonElement
import java.lang.reflect.Type
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import org.java_websocket.client.WebSocketClient
import org.java_websocket.handshake.ServerHandshake
import java.net.URI
import java.util.concurrent.atomic.AtomicBoolean

/**
 * WebSocket管理器 - 负责实时通信连接
 */
class WebSocketManager private constructor(private val context: Context) {
    
    companion object {
        private const val TAG = "WebSocketManager"
        private const val SERVER_PORT = 8080
        
        // 服务器地址配置
        private const val DEFAULT_SERVER_IP = "172.20.0.94"
        private const val PUBLIC_SERVER_URL = "ws://your-ngrok-url.ngrok.io" // 替换为你的ngrok地址
        
        // ngrok配置示例
        // 如果使用ngrok，将上面的地址替换为你的ngrok地址
        // 例如：ws://abc123.ngrok.io
        
        // 连接配置
        private const val RECONNECT_DELAY_MS = 5000L
        private const val HEARTBEAT_INTERVAL_MS = 30000L
        private const val MAX_RECONNECT_ATTEMPTS = 3
        
        // 单例模式
        @Volatile
        private var INSTANCE: WebSocketManager? = null
        
        fun getInstance(context: Context): WebSocketManager {
            return INSTANCE ?: synchronized(this) {
                INSTANCE ?: WebSocketManager(context.applicationContext).also { INSTANCE = it }
            }
        }
    }
    
    private val gson = GsonBuilder()
        .registerTypeAdapter(MessageType::class.java, object : JsonDeserializer<MessageType> {
            override fun deserialize(
                json: JsonElement?,
                typeOfT: Type?,
                context: JsonDeserializationContext?
            ): MessageType? {
                return try {
                    val typeString = json?.asString
                    if (typeString != null) {
                        MessageType.valueOf(typeString)
                    } else {
                        null
                    }
                } catch (e: Exception) {
                    Log.e(TAG, "解析MessageType失败: $json", e)
                    null
                }
            }
        })
        .create()
    private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
    private val isConnected = AtomicBoolean(false)
    private val isConnecting = AtomicBoolean(false)
    
    private val _connectionStatus = MutableStateFlow(ConnectionStatus.DISCONNECTED)
    val connectionStatus: StateFlow<ConnectionStatus> = _connectionStatus
    
    private val _lastMessage = MutableStateFlow<RealtimeMessage?>(null)
    val lastMessage: StateFlow<RealtimeMessage?> = _lastMessage
    
    private var webSocketClient: WebSocketClient? = null
    private var heartbeatJob: Job? = null
    private var reconnectJob: Job? = null
    private var reconnectAttempts = 0
    
    private val messageListeners = mutableListOf<MessageListener>()
    
    init {
        try {
        setupWebSocket()
            Log.d(TAG, "WebSocketManager初始化成功")
        } catch (e: Exception) {
            Log.e(TAG, "WebSocketManager初始化失败", e)
        }
    }
    
    /**
     * 获取服务器地址
     */
    private fun getServerAddress(): String {
        // 优先使用公网地址（如果配置了）
        if (PUBLIC_SERVER_URL != "ws://your-ngrok-url.ngrok.io") {
            return PUBLIC_SERVER_URL
        }
        
        // 使用ServerConfig获取最佳服务器地址
        return try {
            com.example.myapplication.utils.ServerConfig.getServerUrl(context)
        } catch (e: Exception) {
            Log.e(TAG, "获取服务器地址失败，使用默认地址", e)
            // 模拟器特殊处理
            if (isEmulator()) {
                Log.d(TAG, "检测到模拟器，使用10.0.2.2地址")
                "ws://10.0.2.2:$SERVER_PORT"
            } else {
                "ws://$DEFAULT_SERVER_IP:$SERVER_PORT"
            }
        }
    }
    
    /**
     * 检测是否为模拟器
     */
    private fun isEmulator(): Boolean {
        return try {
            val buildModel = android.os.Build.MODEL
            val buildProduct = android.os.Build.PRODUCT
            val buildFingerprint = android.os.Build.FINGERPRINT
            val buildBrand = android.os.Build.BRAND
            val buildDevice = android.os.Build.DEVICE
            
            buildModel.contains("sdk") || 
            buildModel.contains("google_sdk") || 
            buildModel.contains("Emulator") ||
            buildProduct.contains("sdk") ||
            buildProduct.contains("google_sdk") ||
            buildProduct.contains("Emulator") ||
            buildFingerprint.contains("generic") ||
            buildBrand.contains("generic") ||
            buildDevice.contains("generic")
        } catch (e: Exception) {
            Log.e(TAG, "检测模拟器失败", e)
            false
        }
    }
    
    /**
     * 获取服务器URL
     */
    private fun getServerUrl(): String {
        val url = getServerAddress()
        Log.d(TAG, "WebSocket服务器地址: $url")
        return url
    }
    
    /**
     * 设置WebSocket连接
     */
    private fun setupWebSocket() {
        try {
            val uri = URI(getServerUrl())
            webSocketClient = object : WebSocketClient(uri) {
                override fun onOpen(handshakedata: ServerHandshake?) {
                    Log.d(TAG, "WebSocket连接已建立")
                    isConnected.set(true)
                    isConnecting.set(false)
                    _connectionStatus.value = ConnectionStatus.CONNECTED
                    reconnectAttempts = 0 // 重置重连计数器
                    startHeartbeat()
                    
                    // 如果有用户登录，发送认证消息
                    val currentUser = UserSession.currentUser
                    if (currentUser != null) {
                        sendAuthMessage()
                    } else {
                        Log.d(TAG, "用户未登录，等待登录后发送认证消息")
                    }
                }
                
                override fun onMessage(message: String?) {
                    Log.d(TAG, "收到消息: $message")
                    message?.let { handleMessage(it) }
                }
                
                override fun onClose(code: Int, reason: String?, remote: Boolean) {
                    Log.d(TAG, "WebSocket连接关闭: $code - $reason")
                    isConnected.set(false)
                    isConnecting.set(false)
                    _connectionStatus.value = ConnectionStatus.DISCONNECTED
                    stopHeartbeat()
                    
                    if (remote) {
                        // 服务器主动断开，尝试重连
                        scheduleReconnect()
                    }
                }
                
                override fun onError(ex: Exception?) {
                    Log.e(TAG, "WebSocket错误", ex)
                    isConnected.set(false)
                    isConnecting.set(false)
                    _connectionStatus.value = ConnectionStatus.ERROR
                    stopHeartbeat()
                    scheduleReconnect()
                }
            }
        } catch (e: Exception) {
            Log.e(TAG, "WebSocket设置失败", e)
        }
    }
    
    /**
     * 连接WebSocket
     */
    fun connect() {
        if (isConnected.get() || isConnecting.get()) {
            Log.d(TAG, "WebSocket已连接或正在连接中")
            return
        }
        
        // 允许在没有用户登录时也尝试连接（用于预连接）
        val currentUser = UserSession.currentUser
        if (currentUser == null) {
            Log.d(TAG, "用户未登录，但允许预连接WebSocket")
        }
        
        scope.launch {
            try {
                isConnecting.set(true)
                _connectionStatus.value = ConnectionStatus.CONNECTING
                
                // 检查网络连接
                if (!isNetworkAvailable()) {
                    Log.w(TAG, "网络不可用，跳过WebSocket连接")
                    _connectionStatus.value = ConnectionStatus.DISCONNECTED
                    isConnecting.set(false)
                    return@launch
                }
                
                // 重新创建WebSocketClient（避免重用问题）
                setupWebSocket()
                
                val serverUrl = getServerUrl()
                Log.d(TAG, "尝试连接到WebSocket服务器: $serverUrl")
                
                webSocketClient?.connect()
                
                // 等待连接超时（进一步减少超时时间）
                delay(3000L)
                if (!isConnected.get()) {
                    Log.w(TAG, "WebSocket连接超时")
                    _connectionStatus.value = ConnectionStatus.ERROR
                    isConnecting.set(false)
                    // 连接失败时尝试重连
                    scheduleReconnect()
                }
            } catch (e: CancellationException) {
                Log.d(TAG, "连接任务被取消")
                _connectionStatus.value = ConnectionStatus.DISCONNECTED
                isConnecting.set(false)
            } catch (e: Exception) {
                Log.e(TAG, "WebSocket连接失败", e)
                _connectionStatus.value = ConnectionStatus.ERROR
                isConnecting.set(false)
            }
        }
    }
    
    /**
     * 检查网络是否可用
     */
    private fun isNetworkAvailable(): Boolean {
        return try {
            val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as android.net.ConnectivityManager
            val networkInfo = connectivityManager.activeNetworkInfo
            networkInfo?.isConnected == true
        } catch (e: Exception) {
            Log.e(TAG, "检查网络状态失败", e)
            false
        }
    }
    
    /**
     * 断开WebSocket连接
     */
    fun disconnect() {
        Log.d(TAG, "主动断开WebSocket连接")
        stopHeartbeat()
        reconnectJob?.cancel()
        webSocketClient?.close()
        isConnected.set(false)
        isConnecting.set(false)
        _connectionStatus.value = ConnectionStatus.DISCONNECTED
    }
    
    /**
     * 发送消息
     */
    fun sendMessage(message: RealtimeMessage) {
        if (!isConnected.get()) {
            Log.w(TAG, "WebSocket未连接，无法发送消息")
            return
        }
        
        try {
            val jsonMessage = gson.toJson(message)
            webSocketClient?.send(jsonMessage)
            Log.d(TAG, "发送消息: $jsonMessage")
        } catch (e: Exception) {
            Log.e(TAG, "发送消息失败", e)
        }
    }
    
    /**
     * 发送患者上报消息
     */
    fun sendPatientReport(patientId: Long, patientName: String, reporterName: String, department: String) {
        val message = RealtimeMessage(
            type = MessageType.PATIENT_REPORT,
            data = PatientReportData(
                patientId = patientId,
                patientName = patientName,
                reporterName = reporterName,
                department = department,
                timestamp = System.currentTimeMillis()
            )
        )
        sendMessage(message)
    }
    
    /**
     * 发送通知消息
     */
    fun sendNotification(title: String, content: String, targetUserId: Long? = null, targetDepartment: String? = null) {
        val message = RealtimeMessage(
            type = MessageType.NOTIFICATION,
            data = NotificationData(
                title = title,
                content = content,
                targetUserId = targetUserId,
                targetDepartment = targetDepartment,
                timestamp = System.currentTimeMillis()
            )
        )
        sendMessage(message)
    }
    
    /**
     * 处理接收到的消息
     */
    private fun handleMessage(messageJson: String) {
        try {
            val message = gson.fromJson(messageJson, RealtimeMessage::class.java)
            
            // 检查消息类型是否为null
            if (message.type == null) {
                Log.e(TAG, "收到无效消息，MessageType为null: $messageJson")
                return
            }
            
            _lastMessage.value = message
            
            // 通知所有监听器
            messageListeners.forEach { listener ->
                try {
                listener.onMessageReceived(message)
                } catch (e: Exception) {
                    Log.e(TAG, "消息监听器处理失败", e)
                }
            }
            
            Log.d(TAG, "处理消息: ${message.type}")
        } catch (e: Exception) {
            Log.e(TAG, "解析消息失败: $messageJson", e)
        }
    }
    
    /**
     * 发送认证消息
     */
    private fun sendAuthMessage() {
        val currentUser = UserSession.currentUser
        if (currentUser != null) {
            val authMessage = RealtimeMessage(
                type = MessageType.AUTH,
                data = AuthData(
                    userId = currentUser.id,
                    username = currentUser.username,
                    userType = currentUser.userType.name,
                    department = currentUser.department
                )
            )
            sendMessage(authMessage)
        }
    }
    
    /**
     * 用户登录后发送认证消息（公开方法）
     */
    fun sendAuthMessageAfterLogin() {
        if (isConnected.get()) {
            sendAuthMessage()
        } else {
            Log.d(TAG, "WebSocket未连接，无法发送认证消息")
        }
    }
    
    /**
     * 发送用户注册消息
     */
    fun sendUserRegisterMessage(userId: Long, username: String, realName: String, department: String, userType: String, phone: String) {
        if (isConnected.get()) {
            val registerMessage = RealtimeMessage(
                type = MessageType.USER_REGISTER,
                data = UserRegisterData(
                    userId = userId,
                    username = username,
                    realName = realName,
                    department = department,
                    userType = userType,
                    phone = phone,
                    timestamp = System.currentTimeMillis()
                )
            )
            sendMessage(registerMessage)
            Log.d(TAG, "用户注册消息发送成功: $username")
        } else {
            Log.w(TAG, "WebSocket未连接，无法发送用户注册消息")
        }
    }
    
    /**
     * 开始心跳检测
     */
    private fun startHeartbeat() {
        heartbeatJob?.cancel()
        heartbeatJob = scope.launch {
            try {
            while (isConnected.get()) {
                try {
                    val heartbeatMessage = RealtimeMessage(
                        type = MessageType.HEARTBEAT,
                        data = HeartbeatData(timestamp = System.currentTimeMillis())
                    )
                    sendMessage(heartbeatMessage)
                    delay(HEARTBEAT_INTERVAL_MS)
                    } catch (e: CancellationException) {
                        Log.d(TAG, "心跳任务被取消")
                        break
                } catch (e: Exception) {
                    Log.e(TAG, "心跳发送失败", e)
                        delay(HEARTBEAT_INTERVAL_MS) // 继续等待下次心跳
                    }
                }
            } catch (e: CancellationException) {
                Log.d(TAG, "心跳任务被取消")
            } catch (e: Exception) {
                Log.e(TAG, "心跳任务发生异常", e)
            }
        }
    }
    
    /**
     * 停止心跳检测
     */
    private fun stopHeartbeat() {
        heartbeatJob?.cancel()
        heartbeatJob = null
    }
    
    /**
     * 安排重连
     */
    private fun scheduleReconnect() {
        reconnectJob?.cancel()
        
        // 检查重连次数
        if (reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {
            Log.w(TAG, "达到最大重连次数($MAX_RECONNECT_ATTEMPTS)，停止重连")
            _connectionStatus.value = ConnectionStatus.ERROR
            return
        }
        
        reconnectAttempts++
        Log.d(TAG, "安排重连，第${reconnectAttempts}次尝试")
        
        reconnectJob = scope.launch {
            try {
                delay(RECONNECT_DELAY_MS)
                Log.d(TAG, "尝试重新连接WebSocket")
                connect()
            } catch (e: CancellationException) {
                Log.d(TAG, "重连任务被取消")
            } catch (e: Exception) {
                Log.e(TAG, "重连过程中发生异常", e)
                // 重连失败，继续尝试
                scheduleReconnect()
            }
        }
    }
    
    /**
     * 添加消息监听器
     */
    fun addMessageListener(listener: MessageListener) {
        messageListeners.add(listener)
    }
    
    /**
     * 移除消息监听器
     */
    fun removeMessageListener(listener: MessageListener) {
        messageListeners.remove(listener)
    }
    
    /**
     * 检查连接状态
     */
    fun isConnected(): Boolean = isConnected.get()
    
    /**
     * 清理资源
     */
    fun destroy() {
        disconnect()
        scope.cancel()
        messageListeners.clear()
    }
    
    enum class ConnectionStatus {
        DISCONNECTED, CONNECTING, CONNECTED, ERROR
    }
    
    enum class MessageType {
        AUTH, HEARTBEAT, PATIENT_REPORT, NOTIFICATION, DATA_SYNC, USER_STATUS, USER_REGISTER
    }
    
    interface MessageListener {
        fun onMessageReceived(message: RealtimeMessage)
    }
    
    // 消息数据类
    data class RealtimeMessage(
        val type: MessageType,
        val data: Any,
        val timestamp: Long = System.currentTimeMillis()
    )
    
    data class AuthData(
        val userId: Long,
        val username: String,
        val userType: String,
        val department: String
    )
    
    data class HeartbeatData(
        val timestamp: Long
    )
    
    data class PatientReportData(
        val patientId: Long,
        val patientName: String,
        val reporterName: String,
        val department: String,
        val timestamp: Long
    )
    
    data class NotificationData(
        val title: String,
        val content: String,
        val targetUserId: Long?,
        val targetDepartment: String?,
        val timestamp: Long
    )
    
    data class UserRegisterData(
        val userId: Long,
        val username: String,
        val realName: String,
        val department: String,
        val userType: String,
        val phone: String,
        val timestamp: Long
    )
} 